<template>
  <base-dialog @cancel="cancelDialog">
    <div slot="header">{{$t('compute.text_390')}}</div>
    <div slot="body">
      <dialog-selected-tips :count="params.data.length" :action="$t('compute.text_390')" />
      <dialog-table :data="params.data" :columns="columns" />
      <a-form :form="form.fc" hideRequiredMark v-bind="formItemLayout">
        <a-form-item :label="$t('compute.text_106')" class="mb-0">
          <a-row :gutter="20">
            <a-col :span="14">
              <a-form-item :help="help">
                <base-select
                  class="w-100"
                  v-decorator="decorators.network"
                  resource="networks"
                  :params="networkParams"
                  :item.sync="form.fi.network"
                  remote
                  :label-format="item => `${item.name}(${item.guest_ip_start} - ${item.guest_ip_end}, vlan=${item.vlan_id})`"
                  :remote-fn="q => ({ filter: `name.contains(${q})` })"
                  :select-props="{ placeholder: $t('compute.text_195') }"
                  :mapper="mapper" />
              </a-form-item>
            </a-col>
            <a-col :span="10">
              <a-form-item>
                <ip-select v-decorator="decorators.ip" :value="form.fi.ip" :network="form.fi.network" @change="ipChange" />
              </a-form-item>
            </a-col>
            <a-col :span="10" v-if="isSupportIPv6">
              <a-form-item>
                <a-checkbox v-decorator="decorators.require_ipv6">{{ $t('compute.server_create.require_ipv6') }}</a-checkbox>
              </a-form-item>
            </a-col>
          </a-row>
        </a-form-item>
        <a-form-item>
          <a-checkbox v-decorator="decorators.restartNetwork">{{$t('compute.restart_network')}}</a-checkbox>
          <help-tooltip name="restartNetworkToEffectIp" />
        </a-form-item>
      </a-form>
    </div>
    <div slot="footer">
      <a-button type="primary" @click="handleConfirm" :loading="loading">{{ $t('dialog.ok') }}</a-button>
      <a-button @click="cancelDialog">{{ $t('dialog.cancel') }}</a-button>
    </div>
  </base-dialog>
</template>

<script>
import * as R from 'ramda'
import { mapGetters } from 'vuex'
import IpSelect from '@Compute/sections/ServerNetwork/IpSelect'
import { validate, isWithinRange } from '@/utils/validate'
import DialogMixin from '@/mixins/dialog'
import WindowsMixin from '@/mixins/windows'
import { HYPERVISORS_MAP } from '@/constants'
import expectStatus from '@/constants/expectStatus'

export default {
  name: 'VmChangeIpDialog',
  components: {
    IpSelect,
  },
  mixins: [DialogMixin, WindowsMixin],
  data () {
    const validateIp = (rule, value, callback) => {
      let msg
      if (!R.isNil(value) && !R.isEmpty(value)) {
        if (R.isEmpty(this.form.fi.network)) {
          msg = this.$t('compute.text_1191')
          return callback(msg)
        }
        if (validate(value, 'IPv4') !== true) {
          msg = this.$t('compute.text_1192')
          return callback(msg)
        }
        if (!isWithinRange(value, this.form.fi.network.guest_ip_start, this.form.fi.network.guest_ip_end)) {
          msg = this.$t('compute.text_1193')
          return callback(msg)
        }
      }
      return callback()
    }
    return {
      loading: false,
      form: {
        fc: this.$form.createForm(this),
        fi: {
          network: {},
          ip: this.params.data[0].ip_addr,
        },
      },
      decorators: {
        network: [
          'network',
          {
            initialValue: this.params.data[0].network_id,
            rules: [
              { required: true, message: this.$t('compute.text_1191') },
            ],
          },
        ],
        ip: [
          'ip',
          {
            initialValue: this.params.data[0].ip_addr,
            rules: [
              { message: this.$t('common.tips.select', ['IP']), validator: validateIp },
            ],
          },
        ],
        require_ipv6: [
          'require_ipv6',
        ],
        restartNetwork: [
          'restartNetwork',
          {
            valuePropName: 'checked',
            initialValue: true,
          },
        ],
      },
      formItemLayout: {
        wrapperCol: {
          span: 21,
        },
        labelCol: {
          span: 3,
        },
      },
    }
  },
  computed: {
    ...mapGetters(['scope']),
    networkParams () {
      const params = {
        zone: this.params.zone,
        scope: this.scope,
        wire: this.params.data[0].wire_id,
        filter: 'server_type.notin(ipmi, pxe)',
      }
      if (this.params.hypervisor === HYPERVISORS_MAP.esxi.key) {
        params.vpc_id = 'default'
      }
      return params
    },
    columns () {
      const showFields = ['ifname', 'ip_addr', 'mac_addr']
      return this.params.columns.filter((item) => { return showFields.includes(item.field) })
    },
    help () {
      if (this.params.hypervisor === HYPERVISORS_MAP.esxi.key) {
        return this.$t('compute.text_1194')
      }
      return ''
    },
    isSupportIPv6 () {
      return !!this.form.fi.network.guest_ip6_start && !!this.form.fi.network.guest_ip6_end
    },
  },
  methods: {
    ipChange (e) {
      this.form.fi.ip = e
    },
    async handleConfirm () {
      this.loading = true
      let manager = new this.$Manager('servers')
      const values = await this.form.fc.validateFields()
      let netDesc = `${values.network}`
      if (values.ip) {
        netDesc += ':' + values.ip
      }
      if (values.require_ipv6) {
        netDesc += ':[ipv6]'
      }
      try {
        const data = {
          ip_addr: this.params.data[0].ip_addr,
          net_desc: netDesc,
          restart_network: values.restartNetwork,
        }
        await manager.performAction({
          id: this.params.resId,
          action: 'change-ipaddr',
          data,
        })
        this.params.refresh()
        this.$bus.$emit('VMInstanceListSingleRefresh', [this.params.resId, Object.values(expectStatus.server).flat()])
        this.cancelDialog()
        this.$message.success(this.$t('compute.text_423'))
      } finally {
        this.loading = false
        manager = null
      }
    },
    mapper (list) {
      return list.sort((a, b) => { return (b.ports - b.ports_used) - (a.ports - a.ports_used) })
    },
  },
}
</script>
